package frontend;

%%

%byaccj
%public
%line
%class Lexer
%{
  private Parser yyparser;

  public Lexer(java.io.Reader r, Parser yyparser) {
    this(r);
    this.yyparser = yyparser;
  }
  public int getLineNumber() {
    return yyline;
  }
%}

BUY = buy
SELL = sell
BUYSEC = @Buy
SELLSEC = @Sell
USERSEC = @User
PRINT = print
SELECT = select
TF = true | false
SECTOR = sector
VOLUME = volume
PROFIT = profit
LOSS = loss
RISE = rise
FALL = fall
PRICE = open | high | low | close
ALL = all
CROSSOP = crossup | crossdown
LOGICAL = and | or
NOT = not
LITSTRING = \"[^\"]*\"
EQ = ==
LEQ = <=
GEQ = >=
NEQ = [!][=]
CAPIDENT = [A-Z]+{DIGIT}+
COMMENTS = [/][/][^\r\n]*
IDENT = [_a-zA-Z][_a-zA-Z0-9]*
DIGIT = [0-9]
INTEGER = {DIGIT}+
NUM = {DIGIT}+ ("." {DIGIT}+)?
PERCENT = {NUM}%
NL  = \n | \r | \r\n

/* Tokens used in the user defined section */
TYPE = int | float | string | bool | void
RETURN = return
CONTINUE = continue
BREAK = break
WHILE = while
FOR   = for
IF    = if
ELSE  = else
PLUSPLUS = \+\+
MINUSMINUS = --
PLUSEQ = \+=
MINUSEQ = -=
MULEQ = \*=
DIVEQ = \/=
POWEQ = \^=

%%

/* operators */
"+" | 
"-" | 
"*" | 
"/" | 
"^" | 
"(" | 
")"    { return (int) yycharat(0); }

">" |
"<"    { return (int) yycharat(0); }

"."    { return (int) yycharat(0); }
","    { return (int) yycharat(0); }
"="    { return (int) yycharat(0); }
"{"    { return (int) yycharat(0); }
"}"    { return (int) yycharat(0); }
";"    { return (int) yycharat(0); }

/* newline */
{NL}   { return Parser.NL; }

/* comments */
{COMMENTS}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
	return Parser.COMMENTS; }

/* grammar keywords */
{BUY}    { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.BUY; }

{SELL}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.SELL; }

{SELECT}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.SELECT; }

{BUYSEC}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.BUYSEC; }

{SELLSEC}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.SELLSEC; }

{USERSEC}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
	return Parser.USERSEC; }

{PRINT}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.PRINT; }

{RETURN}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.RETURN; }

{BREAK}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.BREAK; }
   
{CONTINUE}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.CONTINUE; }

{WHILE}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.WHILE; }

{FOR}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.FOR; }

{IF}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.IF; }

{ELSE}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.ELSE; }

{TF}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.TF; }

{ALL}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.ALL; }

/* domain specific keywords */
{PRICE}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.PRICE; }

{SECTOR}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.SECTOR; }

{VOLUME}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.VOLUME; }

{PROFIT}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.PROFIT; }

{LOSS}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.LOSS; }
         
{RISE}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.RISE; }

{FALL}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.FALL; }


/* numeric */
/* integer */
{INTEGER}  { yyparser.yylval = new Parser.Semantic(Integer.parseInt(yytext()));
         return Parser.INTEGER; }

/* float */
{NUM}  { yyparser.yylval = new Parser.Semantic(Double.parseDouble(yytext()));
         return Parser.NUM; }

{PERCENT}  { char[] text = yytext().toCharArray();
             text[text.length-1] = ' ';
	yyparser.yylval = new Parser.Semantic(
				Double.parseDouble(new String(text))/100.0 );
         return Parser.PERCENT; }

/* string literal */
{LITSTRING}  { 
	 char[] text = yytext().toCharArray();
	 /* here is a small bug */
	 text[text.length-1] = ' ';
	 text[0] = ' ';
	 String str = new String(text);
	 yyparser.yylval = new Parser.Semantic( str.trim() );
	 return Parser.LITSTRING;
	}

/* operators */
{LOGICAL}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.LOGICAL; }

{NOT}  { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.NOT; }

{EQ}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.EQ; }

{PLUSPLUS}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.PLUSPLUS; }

{MINUSMINUS}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.MINUSMINUS; }

{PLUSEQ}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.PLUSEQ; }

{MINUSEQ}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.MINUSEQ; }


{MULEQ}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.MULEQ; }

{DIVEQ}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.DIVEQ; }

{POWEQ}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.POWEQ; }

{LEQ}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.LEQ; }

{GEQ}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.GEQ; }

{NEQ}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.NEQ; }

{CROSSOP}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.CROSSOP; }

/* types used in customer-function definition */
{TYPE}   { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.TYPE;}

/* identifiers */
{CAPIDENT}  { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.CAPIDENT; }

{IDENT}  { yyparser.yylval = new Parser.Semantic(yytext().toString());
         return Parser.IDENT;}

/* whitespace */
[ \t]+ { }

\b     { System.err.println("Line: " + (getLineNumber()+1));
         System.err.println("Sorry, backspace doesn't work"); System.exit(-1);}

/* error fallback */
[^]    { System.err.println("Line: " + (getLineNumber()+1));
         System.err.println("Error: unexpected character '"+yytext()+"'"); System.exit(-1); }
